import type { IPluginContext } from "@tarojs/service";
import * as path from "path";
import * as fs from "fs";
import webpackChain from "webpack-chain";
import { Project } from "ts-morph";
import * as _ from "lodash";
const project = new Project();
const packageJson = require("../package.json");

/**
 * 编译过程扩展
 */
export default (ctx: IPluginContext, pluginOpts) => {
  const build = () => {
    // console.log(`${packageJson.name} 插件入参：`, pluginOpts, ctx.paths);
    const appConfigPath = ctx.helper.resolveMainFilePath(
      path.resolve(ctx.paths.sourcePath, "./app.config")
    );
    const appConfig = ctx.helper.readConfig(appConfigPath);
    ctx.helper.resolveScriptPath;
    // console.log("appConfigPath", appConfigPath);
    let pages: string[] = [];
    if (appConfig["pages"]) {
      pages = pages.concat(appConfig["pages"]);
    }
    if (appConfig["subPackages"]) {
      appConfig["subPackages"].forEach(
        (element: { root: string; pages: string[] }) => {
          if (element.pages) {
            element.pages.forEach((page: string) => {
              pages.push(element.root + "/" + page);
            });
          }
        }
      );
    }
    // console.log("pages", pages);
    const routeConfigs: {
      page: string;
      _page: string;
      routeConfigPath: string; // 'pages/index/route.config.ts',
      PageParams: boolean;
      PageData: boolean;
      PageBackData: boolean;
      middlewareConfig: any;
    }[] = [];
    const noExistRouteConfigs :{
      page: string;
      _page: string;
    }[] = []
    pages.forEach((page: string) => {
      const dir = page.split("/");
      const last = dir.pop()!;
      dir.push("route.config.ts");
      let configPath = path.resolve(ctx.paths.sourcePath, ...dir);
      if (!fs.existsSync(configPath)) {
        dir.pop();
        dir.push(last);
        dir.push(last + "." + "route.config.ts");
        configPath = path.resolve(ctx.paths.sourcePath, ...dir);
      }
      if (!fs.existsSync(configPath)) {
        // console.log("没有找到route.config.ts",page, configPath)
        noExistRouteConfigs.push({
          page: page,
          _page: page.replace(/\//g, "_"),
        })
        return;
      }
      const file = project.addSourceFileAtPath(configPath);
      routeConfigs.push({
        page: page,
        _page: page.replace(/\//g, "_"),
        routeConfigPath: dir.join("/"),
        PageParams: !!file.getTypeAlias("PageParams"),
        PageData: !!file.getTypeAlias("PageData"),
        PageBackData: !!file.getTypeAlias("PageBackData"),
        middlewareConfig: !!file.getVariableDeclaration("middlewareConfig"),
      });
    });

    // console.log("routeConfigs", routeConfigs);

    const compiledTemplate = _.template(templateText);
    const result = compiledTemplate({
      routeConfigs: routeConfigs,
      noExistRouteConfigs,
    });

    fs.writeFileSync(
      ctx.paths.appPath + "/types/taro-route.config.d.ts",
      result
    );
    // console.log(`${packageJson.name} succcess`);

    // throw "拦截";
  };
  ctx.onBuildStart(() => {
    build();
  });

  ctx.modifyWebpackChain(({}: { chain: webpackChain }) => {
    // console.log('这里可以修改webpack配置')
    // // 示例：利用webpackChain向html中插入脚本
    // if (process.env.TARO_ENV !== 'h5') return
    // chain
    //   .plugin('htmlWebpackPlugin')
    //   .tap(([pluginConfig]) => {
    //     return [
    //       {
    //         ...pluginConfig,
    //         script: pluginConfig.script + 'console.log("向html中插入代码");'
    //       }
    //     ]
    //   })
  });

  ctx.onBuildComplete(() => {
    // console.log("Taro 构建完成！");
  });

  ctx.modifyBuildAssets(({}: { assets: any; miniPlugin: any }) => {
    // console.log('修改编译后的结果')
    // // 示例：修改html产物内容
    // const indexHtml = assets['index.html']
    // if (indexHtml && indexHtml._value) {
    //   indexHtml._value = indexHtml._value.replace(/<title>(.*?)<\/title>/,'<title>被插件修改过的标题</title>')
    // }
  });

  ctx.onBuildFinish(() => {
    build();
    console.log(`${packageJson.name} onBuildFinish`);
  });
};

const templateText = `
<% _.forEach(routeConfigs, function(item) { %>
import type { <% if (item.PageParams == true) { %>  PageParams as <%= item._page %>_PageParams, <% } %>  <% if (item.PageData == true) { %>  PageData as <%= item._page %>_PageData, <% } %>  <% if (item.PageData == true) { %>  PageBackData as <%= item._page %>_PageBackData,  <% } %>  } from "@/<%= item.routeConfigPath %>";
<% }); %>

type MutableRecord<U> = {
  [SubType in keyof U]: {
    url: SubType;
    data?: U[SubType]["data"];
    params?: U[SubType]["params"];
    success?: (res)=>void;
    fail?: (res)=>void;
    onBack?: (backData: U[SubType]["backData"])=>any;
  };
}[keyof U];
export type RoutePageData = MutableRecord<{
  <% _.forEach(routeConfigs, function(item) { %>
    "/<%= item.page %>": {
      data: <%= item._page %>_PageData;
      params: <%= item._page %>_PageParams;
      backData: <%= item._page %>_PageBackData;
    };
  <% }); %>
  <% _.forEach(noExistRouteConfigs, function(item) { %>
    "/<%= item.page %>": {
      data: any;
      params: any;
      backData: any;
    };
  <% }); %>
}>;
`;
